from plyny.workstreams.paths import *
from plyny.workstreams.workstreams import *
from plyny.plio.files import TemporaryDirectory

import unittest


NAME = 'plyny:test:workstreams_test:workstreams'

# Todo:
#   need to test 'list'


class TestCase(unittest.TestCase):
    def test_filestream(self):
        t = TemporaryDirectory()
        f = t.open_within('aaa')
        fw = FileOutputStream(f)
        fw.append('hello')
        fw.extend(['world'])

        self.assertEquals(fw._len, 2)
        fw.close()

        fs = FileInputStream(f)

        self.assertEquals(fs.peek(), 'hello')
        self.assertEquals(list(fs), ['hello', 'world'])
        self.assertEquals(fs.peek(), 'hello')
        # second time
        self.assertEquals(list(fs), ['hello', 'world'])
        self.assertEquals(fs.peek(), 'hello')

    def test_merge(self):
        w = Manager(TemporaryDirectory())
        w.write_only.substream('0').DataTable('a', 'b').add(1, 2).add(3, 4).close()
        w.write_only.substream('1').DataTable('a', 'b').add(5, 6).add(7, 8).close()
        w.write_only.substream('2').DataTable('a', 'b').add(9, 10).add(11, 12).close()

        x = w.open(NAME)
        self.assertTrue(isinstance(x, StreamStreamTable))
        self.assertEquals(len(x), 6)
        self.assertEquals(x.list_of_lists(), [[1, 2], [3, 4], [5, 6], [7, 8],
            [9, 10], [11, 12]])

        x = w.stream.open(NAME)
        self.assertTrue(isinstance(x, StreamStreamTable))
        self.assertEquals(len(x), 6)
        self.assertEquals(x.list_of_lists(), [[1, 2], [3, 4], [5, 6], [7, 8],
            [9, 10], [11, 12]])

    def test_slice(self):
        t = TemporaryDirectory()
        f = t.open_within('aaa')
        fw = FileOutputStream(f)
        fw.append('hello')
        fw.extend(['world', 'ok'])

        self.assertEquals(fw._len, 3)
        fw.close()

        fs = FileInputStream(f)

        l = list(fs.slice(0, 1))
        self.assertEquals(l, ['hello'])

        l = list(fs.slice(1, 2))
        self.assertEquals(l, ['world'])

        l = list(fs.slice(0, 2))
        self.assertEquals(l, ['hello', 'world'])

        l = list(fs.slice(0, None))
        self.assertEquals(l, ['hello', 'world', 'ok'])

        l = list(fs.slice(0, 2))
        self.assertEquals(l, ['hello', 'world'])

        l = list(fs.slice(2))
        self.assertEquals(l, ['hello', 'world'])

        l = list(fs.slice(None))
        self.assertEquals(l, ['hello', 'world', 'ok'])

        l = list(fs.slice(2, 3))
        self.assertEquals(l, ['ok'])

        l = list(fs.slice(0, 3, 2))
        self.assertEquals(l, ['hello', 'ok'])

        w = Manager(TemporaryDirectory())
        w.write_only.DataTable('a').extend(xrange(59)).close()
        d = w.open(NAME)
        x = d.slice(0, None, 2)
        self.assertEquals(len(x), 30)
        self.assertEquals(list(x), range(0, 59, 2))
        x = d.slice(0, 20, 2)
        self.assertEquals(len(x), 10)
        self.assertEquals(list(x), range(0, 20, 2))

        x = d.slice(17, 29, 5)
        self.assertEquals(len(x), 3)
        self.assertEquals(list(x), range(17, 29, 5))

    def test_get_group(self):
        w = Manager(TemporaryDirectory())
        d = w.write_only.DataTable('a', 'b')
        d.extend(list([x, x + 1] for x in xrange(0, 10, 2)))
        d.close()

        self.assertEquals(w.open(NAME).get_group(0, 1).list_of_lists(), [[0,
            1], [2, 3], [4, 5], [6, 7], [8, 9]])

        self.assertEquals((w.open(NAME).get_group(0, 5) +
               w.open(NAME).get_group(1, 5) +
               w.open(NAME).get_group(2, 5) +
               w.open(NAME).get_group(3, 5) +
               w.open(NAME).get_group(4, 5)).list_of_lists(),
               [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]])

        g = w.open(NAME).get_group(1, 2)
        self.assertEquals(len(g), 2)
        self.assertEquals(g.list_of_lists(), [[4, 5], [6, 7]])

        d = w.substream('2').write_only.DataTable('a', 'b')
        d.add(0, 1).add(2, 3).close()
        g = w.open(NAME + '/2').get_group(1, 2)
        self.assertEquals(len(g), 1)
        self.assertEquals(g.list_of_lists(), [[2, 3]])
        g = w.open(NAME + '/2').get_group(0, 2)
        self.assertEquals(len(g), 1)
        self.assertEquals(g.list_of_lists(), [[0, 1]])

    def test_config(self):
        t = TemporaryDirectory()
        w = Manager(t)

        rev = 'abc'

        w.scm_revision = rev
        self.assertEquals(w.scm_revision, rev)

        d = w.DataTable()
        self.assertEquals(d.config().scm_revision, rev)
        d.config().x = 'y'
        self.assertEquals(d.config().x, 'y')
        self.assertRaises(ValueError, lambda x: setattr(x.config(), 'x', 'x'), d)

        d.config().y = 'z'
        self.assertEquals(d.config().y, 'z')
        self.assertEquals(d.config().x, 'y')
        [d.add(i) for i in xrange(3)]
        self.assertEquals(d.config().length, None)
        d.close()
        self.assertEquals(d.config().length, 3)
        self.assertEquals(len(d), 3)
        o = w.open(NAME)
        self.assertEquals(len(o), 3)

    def test_combine(self):
        w = Manager(TemporaryDirectory())
        w.substream('0').DataTable().add(0, 1).close()
        w.substream('1').DataTable().add(2, 3).close()
        w.substream('2').DataTable().add(3, 4).close()

        d = w.open(NAME)
        self.assertEquals(len(d), 3)
        self.assertEquals(d.list_of_lists(), [[0, 1], [2, 3], [3, 4]])

    def test_stream(self):
        t = TemporaryDirectory()
        w = Manager(t)

        x = w.write_only.DataTable('a', 'b')
        x.add(0, 1)
        x.add(1, 2)
        x.add(2, 3)

        x.close()

        m = w.stream.open(NAME)
        self.assertTrue(w.stream._streaming)
        self.assertEquals(m.list_of_lists(), [[0, 1], [1, 2], [2, 3]])
        self.assertEquals(m.list_of_lists(), [[0, 1], [1, 2], [2, 3]])
        m = w.stream.open(NAME)
        self.assertEquals(m.list_of_lists(), [[0, 1], [1, 2], [2, 3]])
        self.assertEquals(m.list_of_lists(), [[0, 1], [1, 2], [2, 3]])

    def test_internal(self):
        import plyny.workstreams.workstreams as w
        i = w._workstream_itr('a')

        f = i.existing_only()
        self.assertTrue(f._ex_existing_only)
        self.assertFalse(f._ex_force)
        self.assertFalse(f._ex_stream)

        f = i.existing_only().force()
        self.assertTrue(f._ex_existing_only)
        self.assertTrue(f._ex_force)
        self.assertFalse(f._ex_stream)

    def x_test_joins(self):
        t = TemporaryDirectory()
        w = Manager(t)

        w.substream('a').DataTable('a', 'b').add(1, 2)
        w.substream('b').DataTable('a', 'c').add(1, 2)

        self.assertEquals(w.outer_join('%s/a,b' % NAME).list_of_lists(), [[1, 2, 2]])

    def x_test_latest(self):
        t = TemporaryDirectory()
        w = Manager(t)

        w.substream('a').DataTable().add(1, 2)
        w.substream('b').DataTable().add(2, 3)

        y = w.latest()
        self.assertEquals(y[0].path.date(), y[1].path.date())

    def test_substream(self):
        t = TemporaryDirectory()
        w = Manager(t)

        base = 'base'
        l = w.substream(base).substream('a').DataTable()
        l.add(1, 2).close()

        x = w.substream(base)
        for i in xrange(3):
            y = x.substream().DataTable('a', 'b')
            y.add(i + 2, i + 3).close()

#        print x.list().workstreams()  # XXX i don't like this
        self.assertEquals(map(str, w.substream(base).list().workstreams()), list('abcd'))  # XXX or this
        x = w.open('%s/base' % NAME)
        self.assertEquals(x.list_of_lists(), [[1, 2], [2, 3], [3, 4], [4, 5]])

    def y_x_test_all_revisions(self):
        t = TemporaryDirectory()
        w = Manager(t)
        # XXX how
#        w.write_only.DataTable()

    def test_splitting(self):
        t = TemporaryDirectory()
        w = Manager(t, compress=True)

        a = w.substream('a').DataTable('b', 'c')
        a.add(1, 2)
        a.close()

        a = w.substream('b').DataTable('b', 'c')
        a.add(3, 4)
        a.close()

        a = w.substream('c').DataTable('b', 'c')
        a.add(5, 6)

        a.close()

        x = w.open('%s/a,b,c' % NAME)
        self.assertEquals(list(list(y) for y in x), [[1, 2], [3, 4], [5, 6]])

#        a = w.substream('a').DataTable('b', 'c')
#        a.add(5, 6)
#        a.close()
#
#        a = w.substream('b').DataTable('b', 'c')
#        a.add(7, 8)
#        a.close()
#
#        x = w.open('%s/a,b' % NAME)
# XXX        self.assertEquals(x.list_of_lists(), [[1, 2], [5, 6], [3, 4], [7, 8]])

    def test_remainder(self):
        t = TemporaryDirectory()
        w = Manager(t, compress=True)

        w.substream('x').substream('y').DataTable().add(1)
        w.substream('x').substream('z').DataTable().add(1)

#        w.substream(

    def y_x_test_creation(self):
        t = TemporaryDirectory()
        w = Manager(t, compress=True)
        x = w.DataTable('x')
        self.assertTrue(isinstance(x, WorkstreamTable))
        x = w.write_only.DataTable('x')
        self.assertTrue(isinstance(x, StreamingWriter))

        x.add(1)
        x.add(2)

        self.assertRaises(NotImplementedError, lambda y: list(y), x)

        x = w.open('%s#a' % NAME)
        self.assertTrue(isinstance(x, DataTable))
        x = w.open('%s#b' % NAME, stream=True)
        self.assertTrue(isinstance(x, StreamingTable))

        self.assertRaises(NotImplementedError, lambda y: list(y), x)
        self.assertEquals(list(iter(x)), [1, 2])

    def y_x_test_d(self):
        t = TemporaryDirectory()
        w = Manager(t)
        wout = w.DataTable('a', 'b', 'c')
        wout.add(*range(3))
        wout.add(0, 5, 9)
        wout.add(1, 9, 12)

    def y_x_test_group(self):
        t = TemporaryDirectory()
        w = Manager(t)
        wout = w.DataTable('a', 'b', 'c')
        wout.add(*range(3))
        wout.add(0, 5, 9)
        wout.add(1, 9, 12)
        wout.close()

        win = w.open('%s' % NAME)
        v = dict(win.group('a'))
        self.assertEquals(list(list(v[0])[0]), range(3))
        self.assertEquals(list(list(v[0])[1]), [0, 5, 9])
        self.assertEquals(list(list(v[1])[0]), [1, 9, 12])

    def x_test_names_minus_substream(self):
        t = TemporaryDirectory()
        w = Manager(t)

        w.substream('a').substream('a').DataTable().add(1, 2)
        w.substream('a').substream('b').DataTable().add(1, 2)
#        w.substream('b').DataTable().add(1, 2)

        self.assertEquals([x[0] for x in w.substream('a').names_minus_substream()], ['a', 'b'])
        self.assertEquals(w.substream('b').names_minus_substream(), [])
        w.substream('b').substream('c').DataTable().add(1, 2)
        self.assertEquals([x[0] for x in w.substream('b').names_minus_substream()], ['c'])
        self.assertEquals(w.substream('c').names_minus_substream(), [])
        self.assertEquals([x[0] for x in w.names_minus_substream()], ['a/a', 'a/b', 'b/c'])


    def x_test_remainder(self):
        t = TemporaryDirectory()
        w = Manager(t)

        x = w.substream('a').substream('a').DataTable().add(1, 2)
        x = w.substream('a').substream('b').DataTable().add(1, 2)
        y = w.substream('b').substream('a').DataTable().add(1, 2)

        x = w.open('%s/a/a' % NAME)
        self.assertEquals(x.path.substreams(), ['a', 'a'])
        x = w.open('%s/a/b' % NAME)
        self.assertEquals(x.path.substreams(), ['a', 'b'])
        y = w.substream('b').remainder('%s/a' % NAME)
#        print y, type(y)
        self.assertEquals(len(y), 1)
        self.assertEquals(y[0][1].name(), '%s/b/b' % NAME)
        y = w.substream('b').remainder('%s/a' % NAME).force()
        self.assertEquals(len(y), 2)
        self.assertEquals(y[0][1].name(), '%s/b/a' % NAME)
        self.assertEquals(y[1][1].name(), '%s/b/b' % NAME)
        y = w.substream('c').substream('a').DataTable().add(1, 2)

        # should be tolerate missing?
#        self.assertRaises(ValueError, lambda x: list(w.substream('b').remainder('%s/a' % NAME, '%s/c' % NAME)), 0)

        y = w.substream('c').substream('b').DataTable().add(1, 2)
        y = w.substream('b').remainder('%s/a' % NAME, '%s/c' % NAME)
        self.assertEquals(y[0][0][0].path.substreams(), ['a', 'b'])
        self.assertEquals(y[0][0][1].path.substreams(), ['c', 'b'])

        w.substream('c').substream('a').DataTable().add(1, 2)  # c/a
        w.substream('d').substream('a').DataTable().add(2, 3)  # d/a
        y = w.substream('c').remainder('%s/d' % NAME)
        w.substream('c').substream('a').DataTable().add(1, 2)
        y = w.substream('c').remainder('%s/d' % NAME)
        self.assertEquals(len(y), 0)
        w.substream('c').substream('b').DataTable().add(1, 2)
        y = w.substream('d').remainder('%s/c' % NAME)
        self.assertEquals(len(y), 1)
        self.assertEquals(y[0][1].name(), '%s/d/b' % NAME) 
        w.substream('c').substream('z').DataTable().add(1, 2)
        w.substream('c').substream('y').DataTable().add(1, 2)
        y = w.substream('d').remainder('%s/c' % NAME)
        self.assertEquals(len(y), 3)
        self.assertEquals(y[0][1].name(), '%s/d/b' % NAME) 
        self.assertEquals(y[1][1].name(), '%s/d/y' % NAME) 
        self.assertEquals(y[2][1].name(), '%s/d/z' % NAME) 

        w.substream('a').substream('c').DataTable().add(1, 2)
        y = w.substream('b').remainder('%s/a' % NAME, '%s/c' % NAME).existing_only()
        self.assertEquals(len(y), 1)
        self.assertEquals(y[0][0][0].path.substreams(), ['a', 'b'])
        self.assertEquals(y[0][0][1].path.substreams(), ['c', 'b'])

        w.substream('c').substream('c').DataTable().add(1, 2)
        y = w.substream('b').remainder('%s/a' % NAME, '%s/c' % NAME).existing_only()
        self.assertEquals(len(y), 2)
        self.assertEquals(y[0][0][0].path.substreams(), ['a', 'b'])
        self.assertEquals(y[0][0][1].path.substreams(), ['c', 'b'])
        self.assertEquals(y[1][0][0].path.substreams(), ['a', 'c'])
        self.assertEquals(y[1][0][1].path.substreams(), ['c', 'c'])

        m = list(w.substream('b').remainder('%s/a' % NAME, '%s/c' % NAME).tolerate_missing().require('%s/a' % NAME))
        self.assertEquals(list(y[0][0].path.substreams() for y in m), [['a', 'b'], ['a', 'c']])
        m = list(w.substream('b').remainder('%s/a' % NAME, '%s/c' % NAME).existing_only())

#        self.assertEquals(list(y[0][0].path.substreams() for y in m), [['c', 'y'], ['c', 'z']])
#        m = list(w.substream('b').remainder('%s/a', '%s/c').tolerate_missing().require('%s/b' % NAME))
#        print list(y[0][0].path.substreams() for y in m)

    def test_bind(self):
        t = TemporaryDirectory()
        w = Manager(t, process='prev')
        w.substream('a').substream('a').DataTable().add(1, 2)
        w.substream('a').substream('b').DataTable().add(1, 2)

        w = Manager(t)

        w.substream('a').substream('a').DataTable().add(1, 2)

#        print w.open('prev/a')
#        print w.bind('prev')

    def test_name(self):
        t = TemporaryDirectory()
        w = Manager(t)

        x = w.substream('a').DataTable()
        x.add(1, 2).close()

#        self.assertEquals(w.name(), '%s' % NAME)
        self.assertEquals(w.substream('b').name(), '%s/b' % NAME)

    def x_test_w(self):
        w = WorkstreamPath.create_with_path(Directory('/'), 'test/a,b')
        self.assertEquals(map(str, w.branches()), ['test/a', 'test/b'])
        w = WorkstreamPath.create_with_path(Directory('/'), 'test/c/a,b')
        self.assertEquals(map(str, w.branches()), ['test/c/a', 'test/c/b'])
        w = WorkstreamPath.create_with_path(Directory('/'), 'test/a,b/d/c,e')
        self.assertEquals(map(str, w.branches()), ['test/a/d/c', 'test/a/d/e', 'test/b/d/c', 'test/b/d/e'])

        t = TemporaryDirectory()
        w = Manager(t)

        w.substream('a').DataTable().add(1, 2)

        x = WorkstreamPath(w._dir, Path('%s' % NAME)).branches()[0]
        self.assertFalse(x.is_workstream())
#        y = x.expand()
#        self.assertEquals(len(y), 1)
#        print y[0]

        x = WorkstreamPath(w._dir, Path('%s/a' % NAME)).branches()[0]
        self.assertTrue(x.is_workstream())

#        self.assertFalse(y[0].is_execution())

        w.DataTable().add(1, 2)
        x = WorkstreamPath(w._dir, Path('%s' % NAME))
        self.assertTrue(x.is_workstream())

        w.substream('b').substream('a').DataTable().add(1, 2)
        w.substream('b').substream('b').DataTable().add(2, 3)

        x = WorkstreamPath(w._dir, Path('%s/b' % NAME))
        y = x.expand()
        self.assertEquals(len(y), 2)
        self.assertEquals(y[0].substreams(), ['b', 'a'])
        self.assertEquals(y[1].substreams(), ['b', 'b'])

        w.substream('b').substream('c').substream('b').DataTable().add(2, 3)
        x = WorkstreamPath(w._dir, Path('%s/b' % NAME))
        y = x.expand()
        self.assertEquals(y[0].substreams(), ['b', 'a'])
        self.assertEquals(y[1].substreams(), ['b', 'b'])
        self.assertEquals(y[2].substreams(), ['b', 'c', 'b'])

        w.DataTable().add(2, 3)
        x = WorkstreamPath(w._dir, Path('%s' % NAME))
        expanded = x.expand()
        self.assertEquals(expanded[0].execution(), 'a')
        self.assertEquals(expanded[1].execution(), 'b')

        x = WorkstreamPath(w._dir, Path(NAME), ['a'])
        y = x.expand()
        self.assertEquals(len(y), 1)
        self.assertEquals(y[0].execution(), 'a')
        x = WorkstreamPath(w._dir, Path(NAME), ['b'])
        y = x.expand()
        self.assertEquals(len(y), 1)
        self.assertEquals(y[0].execution(), 'b')
        x = WorkstreamPath(w._dir, Path(NAME), ['a', 'b'])
        y = x.expand()
        self.assertEquals(len(y), 2)
        self.assertEquals(y[0].execution(), 'a')
        self.assertEquals(y[1].execution(), 'b')

        x = WorkstreamPath.create_with_path(w._dir, Path('%s/a,b' % NAME))
        y = x.expand()
        self.assertEquals(len(y), 4)
        self.assertEquals(y[0].substreams(), ['a'])
        self.assertEquals(y[1].substreams(), ['b', 'a'])
        self.assertEquals(y[2].substreams(), ['b', 'b'])
        self.assertEquals(y[3].substreams(), ['b', 'c', 'b'])

        w.substream('a').DataTable().add(2, 3)
        x = WorkstreamPath.create_with_path(w._dir, Path('%s/a#a,b' % NAME))
        y = x.expand()
        self.assertEquals(len(y), 2)
        self.assertEquals(y[0].execution(), 'a')
        self.assertEquals(y[1].execution(), 'b')

        w.substream('b').DataTable().add(2, 3)
        w.substream('b').DataTable().add(2, 3)
        x = WorkstreamPath.create_with_path(w._dir, Path('%s/a,b#a,b' % NAME))
        y = x.expand()
        self.assertEquals(len(y), 4)
        self.assertEquals(y[0].execution(), 'a')
        self.assertEquals(y[0].substreams(), ['a'])
        self.assertEquals(y[1].execution(), 'b')
        self.assertEquals(y[1].substreams(), ['a'])
        self.assertEquals(y[2].execution(), 'a')
        self.assertEquals(y[2].substreams(), ['b'])
        self.assertEquals(y[3].execution(), 'b')
        self.assertEquals(y[3].substreams(), ['b'])

    def x_test_b(self):
        t = TemporaryDirectory()
        w = Manager(t)
        wout = w.substream('tag_a').DataTable('a', 'b', 'c')
        wout.add(*range(3))
        wout.close()

        wout = w.substream('tag_b').DataTable('a', 'b', 'c')
        wout.add(*range(0, 6, 2))
        wout.close()

        win1 = w.open('%s/tag_a' % NAME)
        win2 = w.open('%s/tag_b' % NAME)

        import datetime
        d1 = datetime.datetime.now()
#        d2 = w.date('%s/tag_a' % NAME)
#        td = d1 - d2
#        self.assertTrue(td.seconds < 5)

        self.assertEquals(list(list(win2)[0]), range(0, 6, 2))

        wout = w.substream('tag_c').DataTable('a', 'd', 'e')
        wout.add(0, 2, 3)
        wout = w.substream('tag_c').DataTable('a', 'd', 'e')
        wout.add(3, 4, 6)
        wout.close()

        self.assertEquals(len(w.open('%s/tag_c' % NAME)), 2)

        win3 = w.open('%s/tag_c#a' % NAME)

        #self.assertRaises(AttributeError, lambda x: list(WorkstreamReader.blend(x, win1, win3)), 'b')
        #self.assertRaises(AttributeError, lambda x: list(win1.join(win3)), 'x')

        win_c = DataTable.join(win1, win3)
        self.assertEquals(list(list(win_c)[0]), [0, 1, 2, 2, 3])

#        self.assertRaises(AttributeError, lambda x: list(WorkstreamReader.zip(x, win1, win3)), 'b')
#        self.assertRaises(AttributeError, lambda x: list(WorkstreamReader.zip(x, win1, win3)), 'x')
#        win_c = list(WorkstreamReader.zip('a', win1, win3))
#        print win_c[0]
#        self.assertEquals(list(a), range(3))
#        self.assertEquals(list(b), [0, 2, 3])

#        win1 = w.open('%s' % NAME)
#        self.assertTrue(isinstance(win1, list))
#        self.assertEquals(len(win1), 2)

        w.substream('tag_a').DataTable('a', 'm', 'n').add(*range(3))
        w.substream('tag_b').DataTable('a', 'm', 'n').add(*range(3, 6))

        a = w.open('%s/tag_a' % NAME)
        if False: # XXX
            a, b = w.open('%s/tag_a,tag_b' % NAME, merge=False)
            a = list(a)
            self.assertEquals(list(a[0]) + list(a[1]), range(3) + range(0, 6, 2))
            a1 = w.open('%s/tag_a,tag_b#a' % NAME)
            b1 = w.open('%s/tag_a,tag_b#b' % NAME)
            self.assertEquals(list(a1), a)
            b1 = list(b1)
            self.assertEquals(list(b1[0]) + list(b1[1]), range(6))
#        self.assertEquals(a, [a1[0], b1[0]])
#        self.assertEquals(b, [a1[1], b1[1]])

    def test_workstream_reader(self):
        w = Manager(TemporaryDirectory())
        d = w.DataTable('a', 'b').extend((x, x + 1) for x in xrange(10))
        self.assertEquals(d.column_names, ('a', 'b'))
        d.close()

        wr = WorkstreamReader(w.get_path().workstreams()[0].current())
        self.assertEquals(wr.column_names, ('a', 'b'))
        self.assertEquals(len(wr), 10)

        wr2 = WorkstreamReader(w.get_path().workstreams()[0].current())
        wrwr = wr + wr2
        self.assertEquals(len(wrwr), 20)
        self.assertEquals(len(wr), 10)

        d = wr.slice(3, 10)
        self.assertEquals(len(d), 7)

        d = wr.slice(3, 20)
        self.assertEquals(len(d), 7)

        d = wrwr.slice(3, 20)
        self.assertEquals(len(d), 17)

    def test_opens(self):
        t = TemporaryDirectory()
        w = Manager(t)

        w.substream('a').DataTable().add(1, 2).close()
        w.substream('b').DataTable().add(3, 4).close()
        w.substream('c').DataTable().add(5, 6).close()

        a = w.open(NAME + '/a')
        b = w.open(NAME + '/b')
        c = w.open(NAME + '/c')

        self.assertEquals(a.list_of_lists(), [[1, 2]])
        self.assertEquals(b.list_of_lists(), [[3, 4]])
        self.assertEquals(c.list_of_lists(), [[5, 6]])

        ap, bp, cp = w.open([NAME + '/a', NAME + '/b', NAME + '/c'], merge=False)
        self.assertEquals(a, ap)
        self.assertNotEquals(a, bp)
        self.assertNotEquals(a, cp)
        self.assertEquals(b, bp)
        self.assertNotEquals(b, cp)
        self.assertEquals(c, cp)

        ap, bp, cp = w.open(NAME + '/a,b,c', merge=False)
        self.assertEquals(a, ap)
        self.assertNotEquals(a, bp)
        self.assertNotEquals(a, cp)
        self.assertEquals(b, bp)
        self.assertNotEquals(b, cp)
        self.assertEquals(c, cp)

    def test_substream_creator(self):
        t = TemporaryDirectory()
        w = Manager(t)
        w.substream('a').substream().DataTable().add(1, 2)
        w.substream('a').substream().DataTable().add(3, 4)

        ws = w.get_path().workstreams()
        self.assertEquals(len(ws), 2)
        self.assertEquals(ws[0].substreams(), ['a', 'a'])
        self.assertEquals(ws[1].substreams(), ['a', 'b'])

    def test_usage(self):
        t = TemporaryDirectory()
        w = Manager(t)
        w.DataTable().add(1, 2).close()

        x = w.open(NAME).usage().get()
        self.assertEquals(len(x), 1)

        x = w.open(NAME).usage().get()
        self.assertEquals(len(x), 2)
        from util.date import parse_datetime_str
        d1 = parse_datetime_str(x[0]['date'])
        d2 = parse_datetime_str(x[1]['date'])
        self.assertTrue(d2 > d1)

    def y_test_workstream_path(self):
        w = WorkstreamPath('/tmp/aaa', '%s/b/c/2011.07.12.13.06.49/a' % NAME)
        self.assertEquals(w.per_execution(), 'a')
        self.assertEquals(w.iteration(), '2011.07.12.13.06.49')
        self.assertEquals(w.process(), '%s' % NAME)
        self.assertEquals(w.substreams(), ['b', 'c'])

    def x_test_sub(self):
        t = TemporaryDirectory()
        w = Manager(t)

        x = w.substream('x').substream('y').DataTable('a', 'b', 'c')
        c = x.path.components()
        # Fails on non unix
        self.assertEquals(c[0], '/')
#        self.assertEquals(c[1], 'tmp')
        self.assertEquals(c[-5], '%s' % NAME)
        self.assertEquals(c[-4], 'x')
        self.assertEquals(c[-3], 'y')
        self.assertEquals(c[-1], 'a')

    def x_test_exists(self):
        t = TemporaryDirectory()
        w = Manager(t)

        w1 = w.DataTable('a')
        self.assertTrue(w.exists('%s' % NAME))
        w2 = w.DataTable('b')
        self.assertTrue(w.exists('%s' % NAME))

#        self.assertFalse(w.exists('%smm' % NAME)) XXX

    def x_test_e(self):
        t = TemporaryDirectory()
        w = Manager(t)
        x = w.write_only.DataTable()
        x.add('hello')
        x.add('world')
#        x = w.open('%s' % NAME)
#        self.assertEquals(x.list_of_lists(), [['hello'], ['world']])

    def x_test_a(self):
        t = TemporaryDirectory()
        w = Manager(t)
        wout = w.DataTable('a', 'b', 'c')
        wout.add(*range(3))
        wout.close()

        list(t)[0].open_within('.m').writer().write('a')
        list(t)[0].open_within('m').writer().write('a')
        self.assertEquals(len(list(list(t)[0])), 4)

        win = w.open('%s' % NAME)
        win = list(w.open('%s' % NAME))

        self.assertEquals(len(win), 1)

        def check_a(item, values):
            self.assertEquals(list(item), values)
            self.assertTrue(hasattr(item, 'a'))
            self.assertTrue(hasattr(item, 'b'))
            self.assertTrue(hasattr(item, 'c'))
            self.assertEquals(item.a, 0)
            self.assertEquals(item.b, 1)
            self.assertEquals(item.c, 2)

        check_a(win[0], range(3))

        wout = w.DataTable('c', 'b', 'a')
        wout.add(*range(2, -1, -1))
        wout.close()

        win = list(w.open('%s' % NAME))

        self.assertEquals(len(win), 2)  # now two readers returned
        self.assertEquals(list(win[0]), range(3))
        self.assertEquals(list(win[1]), range(3))

        # XXX fails self.assertRaises(ValueError, win[0].tape, win[1])

#        win = win[0].tape(win[0])

#        self.assertEquals(map(list, win.slice(0, 1)), [[0, 1], [0, 1]])

    def x_test_open_all(self):
        t = TemporaryDirectory()
        w = Manager(t)
        d = w.substream('A').write_only.DataTable()
        d.add(1, 2)
        d.close()
        d = w.substream('B').write_only.DataTable()
        d.add(3, 4)
        d.close()

#        print w.open('%s' % NAME)
        self.assertEquals(w.open('%s' % NAME).list_of_lists(), [[1, 2], [3, 4]])

    def x_test_dne(self):
        t = TemporaryDirectory()
        w = Manager(t)
#        self.assertRaises(OSError, w.open, '%s/does_not_exist' % NAME) XXX


if __name__ == '__main__':
    unittest.main()
